"""
剧场对话系统
处理角色间的AI对话和交互
支持多角色对话、会话持久化、智能回复生成
"""

import os
import json
import uuid
import requests
import asyncio
import re
from typing import Dict, List, Any, Optional
from dataclasses import dataclass, asdict
from datetime import datetime
from concurrent.futures import ThreadPoolExecutor

from fastapi import FastAPI, HTTPException, BackgroundTasks
from fastapi.middleware.cors import CORSMiddleware
from fastapi.responses import JSONResponse
from pydantic import BaseModel, Field
import uvicorn

# ==================== 数据模型 ====================

@dataclass
class ChatMessage:
    id: str
    character_id: str
    character_name: str
    message: str
    timestamp: datetime
    message_type: str = "dialogue"  # dialogue, action, system

    def to_dict(self):
        """转换为字典格式"""
        return {
            'id': self.id,
            'character_id': self.character_id,
            'character_name': self.character_name,
            'message': self.message,
            'timestamp': self.timestamp.isoformat() if isinstance(self.timestamp, datetime) else self.timestamp,
            'message_type': self.message_type
        }

@dataclass
class ChatSession:
    session_id: str
    theater_title: str
    node_id: str
    node_title: str
    player_character_id: str
    player_character_name: str
    all_characters: List[Dict]
    node_content: str
    character_settings: Dict
    messages: List[ChatMessage]
    created_at: datetime
    last_active: datetime

    def to_dict(self):
        """转换为字典格式"""
        return {
            'session_id': self.session_id,
            'theater_title': self.theater_title,
            'node_id': self.node_id,
            'node_title': self.node_title,
            'player_character_id': self.player_character_id,
            'player_character_name': self.player_character_name,
            'all_characters': self.all_characters,
            'node_content': self.node_content,
            'character_settings': self.character_settings,
            'messages': [msg.to_dict() for msg in self.messages],
            'created_at': self.created_at.isoformat() if isinstance(self.created_at, datetime) else self.created_at,
            'last_active': self.last_active.isoformat() if isinstance(self.last_active, datetime) else self.last_active
        }

# ==================== API请求模型 ====================

class StartChatRequest(BaseModel):
    theater_title: str
    node_id: str
    node_title: str
    node_content: str
    player_character_id: str
    all_characters: List[Dict]
    character_settings: Dict = Field(default={})

class SendMessageRequest(BaseModel):
    session_id: str
    message: str

class GetSessionRequest(BaseModel):
    session_id: str

class ApiResponse(BaseModel):
    success: bool
    message: str
    data: Optional[Dict[str, Any]] = None
    error_code: Optional[str] = None

# ==================== 全局存储 ====================

# 存储聊天会话（内存中）
chat_sessions: Dict[str, ChatSession] = {}

# ==================== AI对话处理器 ====================

class TheaterChatHandler:
    def __init__(self):
        self.api_key = os.getenv('GEEKAI_API_KEY')
        if not self.api_key:
            raise ValueError("请设置GEEKAI_API_KEY环境变量")
        
        self.base_url = 'https://geekai.co/api/v1/chat/completions'
        self.headers = {
            'Authorization': f'Bearer {self.api_key}',
            'Content-Type': 'application/json'
        }
        
        # 确保存储目录存在
        self.storage_dir = "chat_sessions"
        os.makedirs(self.storage_dir, exist_ok=True)

    async def call_ai_api(self, messages: List[Dict], temperature: float = 0.8) -> str:
        """调用AI API"""
        payload = {
            "model": "gpt-4o-mini",
            "messages": messages,
            "temperature": temperature,
            "max_tokens": 500
        }
        
        loop = asyncio.get_event_loop()
        
        def sync_call():
            try:
                response = requests.post(
                    self.base_url,
                    headers=self.headers,
                    json=payload,
                    timeout=30
                )
                response.raise_for_status()
                result = response.json()
                return result['choices'][0]['message']['content']
            except Exception as e:
                raise Exception(f"AI API调用失败: {e}")
        
        with ThreadPoolExecutor() as executor:
            return await loop.run_in_executor(executor, sync_call)

    def create_chat_session(self, request: StartChatRequest) -> ChatSession:
        """创建聊天会话"""
        session_id = str(uuid.uuid4())
        
        # 找到玩家角色
        player_character = None
        for char in request.all_characters:
            if char['id'] == request.player_character_id:
                player_character = char
                break
        
        if not player_character:
            raise Exception("找不到指定的玩家角色")
        
        session = ChatSession(
            session_id=session_id,
            theater_title=request.theater_title,
            node_id=request.node_id,
            node_title=request.node_title,
            player_character_id=request.player_character_id,
            player_character_name=player_character['name'],
            all_characters=request.all_characters,
            node_content=request.node_content,
            character_settings=request.character_settings,
            messages=[],
            created_at=datetime.now(),
            last_active=datetime.now()
        )
        
        # 添加系统消息（节点内容）
        system_message = ChatMessage(
            id=str(uuid.uuid4()),
            character_id="system",
            character_name="旁白",
            message=self.extract_text_from_html(request.node_content),
            timestamp=datetime.now(),
            message_type="system"
        )
        session.messages.append(system_message)
        
        chat_sessions[session_id] = session
        return session

    def extract_text_from_html(self, html_content: str) -> str:
        """从HTML中提取纯文本"""
        if not html_content:
            return ""
        
        # 简单的HTML标签移除
        clean = re.compile('<.*?>')
        text = re.sub(clean, '', html_content)
        
        # 清理多余的空白字符
        text = re.sub(r'\s+', ' ', text).strip()
        
        return text if text else "场景开始..."

    async def generate_npc_response(self, session: ChatSession, player_message: str) -> List[ChatMessage]:
        """生成NPC角色的回复"""
        try:
            # 构建对话上下文
            context_messages = self.build_conversation_context(session, player_message)
            
            # 获取NPC角色列表（排除玩家角色）
            npc_characters = [char for char in session.all_characters 
                             if char['id'] != session.player_character_id]
            
            if not npc_characters:
                print("警告：没有找到NPC角色")
                return []
            
            responses = []
            
            # 选择1-2个NPC回复（基于对话逻辑选择最相关的）
            responding_npcs = self.select_responding_npcs(npc_characters, session, player_message)
            
            for npc in responding_npcs:
                try:
                    # 为特定NPC构建prompt
                    npc_prompt = self.build_npc_prompt(session, npc, player_message)
                    full_context = context_messages + [{"role": "user", "content": npc_prompt}]
                    
                    # 调用AI生成回复
                    ai_response = await self.call_ai_api(full_context, temperature=0.8)
                    
                    # 清理回复内容
                    cleaned_response = self.clean_ai_response(ai_response, npc['name'])
                    
                    if cleaned_response and len(cleaned_response.strip()) > 0:
                        npc_message = ChatMessage(
                            id=str(uuid.uuid4()),
                            character_id=npc['id'],
                            character_name=npc['name'],
                            message=cleaned_response,
                            timestamp=datetime.now(),
                            message_type="dialogue"
                        )
                        responses.append(npc_message)
                        print(f"✅ {npc['name']} 回复: {cleaned_response[:50]}...")
                        
                        # 短暂延迟，模拟思考时间
                        await asyncio.sleep(0.5)
                    else:
                        print(f"警告：{npc['name']} 生成了空回复")
                        
                except Exception as e:
                    print(f"为NPC {npc['name']} 生成回复失败: {e}")
                    # 生成一个简单的备用回复
                    fallback_message = ChatMessage(
                        id=str(uuid.uuid4()),
                        character_id=npc['id'],
                        character_name=npc['name'],
                        message=self.generate_fallback_response(npc['name'], player_message),
                        timestamp=datetime.now(),
                        message_type="dialogue"
                    )
                    responses.append(fallback_message)
            
            return responses
            
        except Exception as e:
            print(f"生成NPC回复时出错: {e}")
            return []

    def select_responding_npcs(self, npc_characters: List[Dict], session: ChatSession, player_message: str) -> List[Dict]:
        """智能选择应该回复的NPC"""
        if len(npc_characters) == 0:
            return []
        elif len(npc_characters) == 1:
            return npc_characters
        elif len(npc_characters) == 2:
            return npc_characters  # 两个角色都回复
        else:
            # 超过2个角色时，选择最多2个回复
            # 这里可以加入更复杂的逻辑，比如基于角色关系、上次发言时间等
            return npc_characters[:2]

    def generate_fallback_response(self, character_name: str, player_message: str) -> str:
        """生成备用回复"""
        fallback_responses = [
            f"{character_name}若有所思地点了点头。",
            f"{character_name}正在仔细思考你的话。",
            f"{character_name}看起来对你的话很感兴趣。",
            f"{character_name}沉默了一会儿，似乎在消化你说的内容。",
            f"{character_name}微笑着看向你，等待着什么。"
        ]
        import random
        return random.choice(fallback_responses)

    def build_conversation_context(self, session: ChatSession, new_message: str) -> List[Dict]:
        """构建对话上下文"""
        # 系统prompt
        system_prompt = f"""
你正在参与一个名为《{session.theater_title}》的互动剧场体验。

当前场景：{session.node_title}
场景描述：{self.extract_text_from_html(session.node_content)}

角色设定：
{self.format_characters_info(session.all_characters)}

玩家角色：{session.player_character_name}

重要指示：
1. 你需要扮演除了玩家角色外的其他角色
2. 根据各角色的性格和背景生成符合逻辑的对话
3. 回复要推进剧情发展，与场景氛围相符
4. 保持角色的一致性和个性化
5. 回复长度控制在50-150字之间
6. 只返回角色说的话，不要包含动作描述或其他格式

当前剧情发展：玩家角色刚刚说了话，需要其他角色做出合适的回应。
"""
        
        context = [{"role": "system", "content": system_prompt}]
        
        # 添加最近的对话历史（最多8条，避免上下文过长）
        recent_messages = session.messages[-8:] if len(session.messages) > 8 else session.messages
        
        for msg in recent_messages:
            if msg.message_type == "dialogue":
                role = "assistant" if msg.character_id != session.player_character_id else "user"
                content = f"{msg.character_name}: {msg.message}"
                context.append({"role": role, "content": content})
            elif msg.message_type == "system":
                # 系统消息作为助理消息
                context.append({"role": "assistant", "content": f"[场景描述] {msg.message}"})
        
        return context

    def build_npc_prompt(self, session: ChatSession, npc: Dict, player_message: str) -> str:
        """为特定NPC构建prompt"""
        character_setting = session.character_settings.get(npc['id'], {})
        behaviors = character_setting.get('behaviors', [])
        conditions = character_setting.get('conditions', [])
        
        # 获取角色的最近活动
        recent_messages = [msg for msg in session.messages[-5:] if msg.character_id == npc['id']]
        recent_activity = f"最近发言次数: {len(recent_messages)}" if recent_messages else "尚未发言"
        
        prompt = f"""
现在请你专门扮演角色：{npc['name']}

角色详细信息：
- 姓名：{npc['name']}  
- 背景描述：{npc.get('description', '暂无描述')}
- 行为特点：{', '.join(behaviors) if behaviors else '待发掘'}
- {recent_activity}

当前情况：
玩家角色 {session.player_character_name} 刚刚说："{player_message}"

请以 {npc['name']} 的身份、语气和性格来回应。要求：
1. 完全符合 {npc['name']} 的性格特点
2. 回应要自然流畅，推进对话发展  
3. 考虑当前场景氛围和剧情需要
4. 回复长度50-120字左右
5. 只返回对话内容，不要包含角色名称前缀或任何格式标记

请直接以 {npc['name']} 的身份回复：
"""
        
        return prompt

    def format_characters_info(self, characters: List[Dict]) -> str:
        """格式化角色信息"""
        info_lines = []
        for char in characters:
            desc = char.get('description', '暂无描述')
            # 截取描述的前100个字符，避免太长
            short_desc = desc[:100] + "..." if len(desc) > 100 else desc
            info_lines.append(f"- {char['name']}: {short_desc}")
        return '\n'.join(info_lines)

    def clean_ai_response(self, response: str, character_name: str) -> str:
        """清理AI回复内容"""
        if not response:
            return ""
            
        # 移除可能的角色名称前缀
        prefixes_to_remove = [
            f"{character_name}:",
            f"{character_name}：",
            f"「{character_name}」:",
            f"【{character_name}】:",
            f"{character_name}说:",
            f"{character_name}说：",
        ]
        
        for prefix in prefixes_to_remove:
            if response.startswith(prefix):
                response = response[len(prefix):].strip()
                break
        
        # 移除引号
        quote_pairs = [
            ('"', '"'),
            ('"', '"'),
            ("'", "'"),
            ('「', '」'),
            ('『', '』'),
        ]
        
        for start_quote, end_quote in quote_pairs:
            if response.startswith(start_quote) and response.endswith(end_quote):
                response = response[1:-1].strip()
                break
        
        # 移除多余的空白字符
        response = re.sub(r'\s+', ' ', response).strip()
        
        # 确保回复不为空
        if not response:
            return f"（{character_name}沉思片刻...）"
            
        return response

    def add_player_message(self, session_id: str, message: str) -> ChatMessage:
        """添加玩家消息"""
        if session_id not in chat_sessions:
            raise Exception("会话不存在")
        
        session = chat_sessions[session_id]
        
        player_message = ChatMessage(
            id=str(uuid.uuid4()),
            character_id=session.player_character_id,
            character_name=session.player_character_name,
            message=message.strip(),
            timestamp=datetime.now(),
            message_type="dialogue"
        )
        
        session.messages.append(player_message)
        session.last_active = datetime.now()
        
        return player_message

    def save_session_to_storage(self, session_id: str):
        """保存会话到持久化存储"""
        if session_id not in chat_sessions:
            return
        
        session = chat_sessions[session_id]
        
        try:
            # 序列化会话数据
            session_data = session.to_dict()
            
            # 保存到文件
            filename = f"{self.storage_dir}/session_{session_id}.json"
            with open(filename, 'w', encoding='utf-8') as f:
                json.dump(session_data, f, ensure_ascii=False, indent=2)
                
            print(f"✅ 会话 {session_id} 已保存到 {filename}")
            
        except Exception as e:
            print(f"❌ 保存会话 {session_id} 失败: {e}")

    def load_session_from_storage(self, session_id: str) -> Optional[ChatSession]:
        """从持久化存储加载会话"""
        filename = f"{self.storage_dir}/session_{session_id}.json"
        
        if not os.path.exists(filename):
            return None
        
        try:
            with open(filename, 'r', encoding='utf-8') as f:
                session_data = json.load(f)
            
            # 重建ChatMessage对象
            messages = []
            for msg_data in session_data['messages']:
                # 处理时间戳
                timestamp = msg_data['timestamp']
                if isinstance(timestamp, str):
                    try:
                        timestamp = datetime.fromisoformat(timestamp.replace('Z', '+00:00'))
                    except:
                        timestamp = datetime.now()
                
                msg = ChatMessage(
                    id=msg_data['id'],
                    character_id=msg_data['character_id'],
                    character_name=msg_data['character_name'],
                    message=msg_data['message'],
                    timestamp=timestamp,
                    message_type=msg_data.get('message_type', 'dialogue')
                )
                messages.append(msg)
            
            # 处理会话时间戳
            created_at = session_data['created_at']
            if isinstance(created_at, str):
                try:
                    created_at = datetime.fromisoformat(created_at.replace('Z', '+00:00'))
                except:
                    created_at = datetime.now()
            
            last_active = session_data['last_active']
            if isinstance(last_active, str):
                try:
                    last_active = datetime.fromisoformat(last_active.replace('Z', '+00:00'))
                except:
                    last_active = datetime.now()
            
            # 重建ChatSession对象
            session = ChatSession(
                session_id=session_data['session_id'],
                theater_title=session_data['theater_title'],
                node_id=session_data['node_id'],
                node_title=session_data['node_title'],
                player_character_id=session_data['player_character_id'],
                player_character_name=session_data['player_character_name'],
                all_characters=session_data['all_characters'],
                node_content=session_data['node_content'],
                character_settings=session_data['character_settings'],
                messages=messages,
                created_at=created_at,
                last_active=last_active
            )
            
            chat_sessions[session_id] = session
            print(f"✅ 会话 {session_id} 已从存储加载")
            return session
            
        except Exception as e:
            print(f"❌ 加载会话 {session_id} 失败: {e}")
            return None

    def list_stored_sessions(self) -> List[Dict]:
        """列出所有存储的会话"""
        sessions_info = []
        
        if not os.path.exists(self.storage_dir):
            return sessions_info
            
        try:
            for filename in os.listdir(self.storage_dir):
                if filename.startswith("session_") and filename.endswith(".json"):
                    session_id = filename[8:-5]  # 移除 "session_" 前缀和 ".json" 后缀
                    
                    try:
                        with open(f"{self.storage_dir}/{filename}", 'r', encoding='utf-8') as f:
                            session_data = json.load(f)
                        
                        sessions_info.append({
                            "session_id": session_data['session_id'],
                            "theater_title": session_data['theater_title'],
                            "node_title": session_data['node_title'],
                            "player_character_name": session_data['player_character_name'],
                            "message_count": len(session_data['messages']),
                            "last_active": session_data['last_active'],
                            "status": "stored"
                        })
                    except Exception as e:
                        print(f"读取会话文件 {filename} 失败: {e}")
                        continue
                        
        except Exception as e:
            print(f"列出存储会话失败: {e}")
        
        return sessions_info

# ==================== FastAPI应用 ====================

app = FastAPI(
    title="剧场对话系统",
    description="处理剧场角色间的AI对话和交互",
    version="1.0.0",
    docs_url="/docs",
    redoc_url="/redoc"
)

app.add_middleware(
    CORSMiddleware,
    allow_origins=["*"],
    allow_credentials=True,
    allow_methods=["*"],
    allow_headers=["*"],
)

# 初始化对话处理器
chat_handler = None
try:
    chat_handler = TheaterChatHandler()
    print("✅ 对话处理器初始化成功")
except Exception as e:
    print(f"❌ 对话处理器初始化失败: {e}")

# ==================== API端点 ====================

@app.get("/", response_model=ApiResponse)
async def root():
    """根端点 - 系统状态"""
    return ApiResponse(
        success=True,
        message="剧场对话系统正在运行",
        data={
            "version": "1.0.0",
            "active_sessions": len(chat_sessions),
            "handler_status": "ready" if chat_handler else "not_initialized",
            "storage_dir": chat_handler.storage_dir if chat_handler else None,
            "timestamp": datetime.now().isoformat()
        }
    )

@app.get("/health")
async def health_check():
    """健康检查"""
    try:
        if not chat_handler:
            return {
                "status": "unhealthy",
                "message": "对话处理器未初始化",
                "timestamp": datetime.now().isoformat()
            }
        
        # 检查API密钥
        api_key = os.getenv('GEEKAI_API_KEY')
        if not api_key:
            return {
                "status": "unhealthy", 
                "message": "API密钥未配置",
                "timestamp": datetime.now().isoformat()
            }
        
        # 检查存储目录
        if not os.path.exists(chat_handler.storage_dir):
            return {
                "status": "warning",
                "message": "存储目录不存在",
                "timestamp": datetime.now().isoformat()
            }
        
        return {
            "status": "healthy",
            "message": "系统运行正常",
            "active_sessions": len(chat_sessions),
            "storage_sessions": len(chat_handler.list_stored_sessions()),
            "timestamp": datetime.now().isoformat()
        }
        
    except Exception as e:
        return {
            "status": "error",
            "message": f"健康检查失败: {str(e)}",
            "timestamp": datetime.now().isoformat()
        }

@app.post("/chat/start", response_model=ApiResponse)
async def start_chat_session(request: StartChatRequest):
    """开始聊天会话"""
    try:
        if not chat_handler:
            raise HTTPException(
                status_code=500, 
                detail="对话处理器未初始化，请检查API密钥配置"
            )
        
        # 验证请求数据
        if not request.theater_title or not request.node_title:
            raise HTTPException(
                status_code=400,
                detail="剧场标题和节点标题不能为空"
            )
            
        if not request.player_character_id or not request.all_characters:
            raise HTTPException(
                status_code=400,
                detail="必须指定玩家角色和角色列表"
            )
        
        # 创建会话
        session = chat_handler.create_chat_session(request)
        
        # 保存会话
        chat_handler.save_session_to_storage(session.session_id)
        
        print(f"🎭 创建新会话: {session.session_id} - {request.theater_title}")
        
        return ApiResponse(
            success=True,
            message="聊天会话创建成功",
            data={
                "session_id": session.session_id,
                "theater_title": session.theater_title,
                "node_title": session.node_title,
                "player_character_name": session.player_character_name,
                "all_characters": [{"id": c["id"], "name": c["name"]} for c in session.all_characters],
                "initial_messages": [msg.to_dict() for msg in session.messages],
                "created_at": session.created_at.isoformat()
            }
        )
        
    except HTTPException:
        raise
    except Exception as e:
        print(f"❌ 创建聊天会话失败: {e}")
        raise HTTPException(
            status_code=500, 
            detail=f"创建会话失败: {str(e)}"
        )

@app.post("/chat/message", response_model=ApiResponse)
async def send_message(request: SendMessageRequest):
    """发送消息并获取AI回复"""
    try:
        if not chat_handler:
            raise HTTPException(
                status_code=500,
                detail="对话处理器未初始化"
            )
        
        # 验证消息内容
        if not request.message or not request.message.strip():
            raise HTTPException(
                status_code=400,
                detail="消息内容不能为空"
            )
        
        if len(request.message) > 1000:
            raise HTTPException(
                status_code=400,
                detail="消息长度不能超过1000字符"
            )
        
        # 检查会话是否存在
        if request.session_id not in chat_sessions:
            # 尝试从存储中加载
            session = chat_handler.load_session_from_storage(request.session_id)
            if not session:
                raise HTTPException(
                    status_code=404,
                    detail="会话不存在或已过期"
                )
        
        print(f"💬 收到消息: {request.session_id} - {request.message[:50]}...")
        
        # 添加玩家消息
        player_message = chat_handler.add_player_message(request.session_id, request.message)
        
        # 生成NPC回复
        session = chat_sessions[request.session_id]
        npc_responses = await chat_handler.generate_npc_response(session, request.message)
        
        # 添加NPC回复到会话
        session.messages.extend(npc_responses)
        session.last_active = datetime.now()
        
        # 保存会话
        chat_handler.save_session_to_storage(request.session_id)
        
        # 返回所有新消息
        all_new_messages = [player_message] + npc_responses
        
        print(f"✅ 消息处理完成: 1条用户消息 + {len(npc_responses)}条AI回复")
        
        return ApiResponse(
            success=True,
            message="消息发送成功",
            data={
                "new_messages": [msg.to_dict() for msg in all_new_messages],
                "session_info": {
                    "total_messages": len(session.messages),
                    "last_active": session.last_active.isoformat(),
                    "npc_response_count": len(npc_responses)
                }
            }
        )
        
    except HTTPException:
        raise
    except Exception as e:
        print(f"❌ 发送消息失败: {e}")
        raise HTTPException(
            status_code=500,
            detail=f"消息处理失败: {str(e)}"
        )

@app.get("/chat/session/{session_id}", response_model=ApiResponse)
async def get_chat_session(session_id: str):
    """获取聊天会话详情"""
    try:
        if not chat_handler:
            raise HTTPException(
                status_code=500,
                detail="对话处理器未初始化"
            )
        
        # 检查内存中的会话
        if session_id in chat_sessions:
            session = chat_sessions[session_id]
        else:
            # 从存储中加载
            session = chat_handler.load_session_from_storage(session_id)
            if not session:
                raise HTTPException(
                    status_code=404,
                    detail="会话不存在"
                )
        
        return ApiResponse(
            success=True,
            message="获取会话成功",
            data={
                "session_info": {
                    "session_id": session.session_id,
                    "theater_title": session.theater_title,
                    "node_title": session.node_title,
                    "player_character_name": session.player_character_name,
                    "created_at": session.created_at.isoformat(),
                    "last_active": session.last_active.isoformat(),
                    "message_count": len(session.messages)
                },
                "messages": [msg.to_dict() for msg in session.messages],
                "characters": [{"id": c["id"], "name": c["name"]} for c in session.all_characters]
            }
        )
        
    except HTTPException:
        raise
    except Exception as e:
        print(f"❌ 获取会话失败: {e}")
        raise HTTPException(
            status_code=500,
            detail=f"获取会话失败: {str(e)}"
        )

@app.get("/chat/sessions", response_model=ApiResponse)
async def list_chat_sessions():
    """列出所有会话"""
    try:
        sessions_info = []
        
        # 内存中的活跃会话
        for session in chat_sessions.values():
            sessions_info.append({
                "session_id": session.session_id,
                "theater_title": session.theater_title,
                "node_title": session.node_title,
                "player_character_name": session.player_character_name,
                "message_count": len(session.messages),
                "created_at": session.created_at.isoformat(),
                "last_active": session.last_active.isoformat(),
                "status": "active"
            })
        
        # 存储中的会话
        if chat_handler:
            stored_sessions = chat_handler.list_stored_sessions()
            for stored_session in stored_sessions:
                # 避免重复（如果已经在内存中）
                if stored_session["session_id"] not in chat_sessions:
                    sessions_info.append(stored_session)
        
        # 按最后活动时间排序
        sessions_info.sort(key=lambda x: x.get("last_active", ""), reverse=True)
        
        return ApiResponse(
            success=True,
            message="获取会话列表成功",
            data={
                "sessions": sessions_info,
                "total": len(sessions_info),
                "active_count": len([s for s in sessions_info if s.get("status") == "active"]),
                "stored_count": len([s for s in sessions_info if s.get("status") == "stored"])
            }
        )
        
    except Exception as e:
        print(f"❌ 获取会话列表失败: {e}")
        raise HTTPException(
            status_code=500,
            detail=f"获取会话列表失败: {str(e)}"
        )

@app.delete("/chat/session/{session_id}", response_model=ApiResponse)
async def delete_chat_session(session_id: str):
    """删除会话"""
    try:
        deleted_from = []
        
        # 从内存中删除
        if session_id in chat_sessions:
            del chat_sessions[session_id]
            deleted_from.append("memory")
        
        # 从存储中删除
        if chat_handler:
            filename = f"{chat_handler.storage_dir}/session_{session_id}.json"
            if os.path.exists(filename):
                os.remove(filename)
                deleted_from.append("storage")
        
        if not deleted_from:
            raise HTTPException(
                status_code=404,
                detail="会话不存在"
            )
        
        return ApiResponse(
            success=True,
            message=f"会话已删除 (从 {', '.join(deleted_from)} 中删除)",
            data={
                "session_id": session_id,
                "deleted_from": deleted_from
            }
        )
        
    except HTTPException:
        raise
    except Exception as e:
        print(f"❌ 删除会话失败: {e}")
        raise HTTPException(
            status_code=500,
            detail=f"删除会话失败: {str(e)}"
        )

@app.post("/chat/clear", response_model=ApiResponse)
async def clear_all_sessions():
    """清除所有会话（慎用）"""
    try:
        cleared_count = 0
        
        # 清除内存中的会话
        memory_count = len(chat_sessions)
        chat_sessions.clear()
        cleared_count += memory_count
        
        # 清除存储中的会话
        storage_count = 0
        if chat_handler and os.path.exists(chat_handler.storage_dir):
            for filename in os.listdir(chat_handler.storage_dir):
                if filename.startswith("session_") and filename.endswith(".json"):
                    os.remove(f"{chat_handler.storage_dir}/{filename}")
                    storage_count += 1
        
        cleared_count += storage_count
        
        return ApiResponse(
            success=True,
            message=f"已清除所有会话",
            data={
                "memory_sessions_cleared": memory_count,
                "storage_sessions_cleared": storage_count,
                "total_cleared": cleared_count
            }
        )
        
    except Exception as e:
        print(f"❌ 清除会话失败: {e}")
        raise HTTPException(
            status_code=500,
            detail=f"清除会话失败: {str(e)}"
        )

# ==================== 错误处理 ====================

@app.exception_handler(HTTPException)
async def http_exception_handler(request, exc):
    """HTTP异常处理"""
    return JSONResponse(
        status_code=exc.status_code,
        content={
            "success": False,
            "message": exc.detail,
            "error_code": f"HTTP_{exc.status_code}",
            "timestamp": datetime.now().isoformat()
        }
    )

@app.exception_handler(Exception)
async def general_exception_handler(request, exc):
    """通用异常处理"""
    print(f"❌ 服务器错误: {exc}")
    return JSONResponse(
        status_code=500,
        content={
            "success": False,
            "message": f"服务器内部错误: {str(exc)}",
            "error_code": "INTERNAL_SERVER_ERROR",
            "timestamp": datetime.now().isoformat()
        }
    )

# ==================== 启动配置 ====================

def main():
    """主函数 - 启动检查"""
    print("🎭 剧场对话系统")
    print("=" * 50)
    
    # 检查API密钥
    api_key = os.getenv('GEEKAI_API_KEY')
    if not api_key:
        print("⚠️  请设置GEEKAI_API_KEY环境变量")
        print("   Linux/Mac: export GEEKAI_API_KEY='your-api-key'")
        print("   Windows: set GEEKAI_API_KEY=your-api-key")
        return False
    
    print("✅ API密钥已配置")
    
    # 检查对话处理器
    if not chat_handler:
        print("❌ 对话处理器初始化失败")
        return False
    
    print("✅ 对话处理器初始化成功")
    print(f"📁 会话存储目录: {chat_handler.storage_dir}")
    
    # 显示存储的会话
    stored_sessions = chat_handler.list_stored_sessions()
    print(f"💾 已存储会话: {len(stored_sessions)} 个")
    
    print("\n🚀 启动信息:")
    print("   - 端口: 8001")
    print("   - 文档: http://localhost:8001/docs")
    print("   - 健康检查: http://localhost:8001/health")
    print("   - Redoc: http://localhost:8001/redoc")
    print("\n📝 支持的功能:")
    print("   - 多角色AI对话")
    print("   - 会话持久化")
    print("   - 上下文记忆")
    print("   - 智能回复生成")
    print("   - RESTful API")
    
    print("\n按 Ctrl+C 停止服务")
    print("=" * 50)
    
    return True

if __name__ == "__main__":
    if main():
        uvicorn.run(
            "theater_chat:app",
            host="0.0.0.0",
            port=8001,
            reload=True,
            log_level="info",
            access_log=True
        )
    else:
        print("❌ 启动失败，请检查配置")
